/*
 * Copyright (C) 2014-2016 Dominik Schürmann <dominik@dominikschuermann.de>
 * Copyright (C) 2013 Antarix Tandon
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.sufficientlysecure.htmltextview;

import android.content.Context;
import android.graphics.Point;
import android.graphics.drawable.Drawable;
import android.text.Editable;
import android.text.Html;
import android.text.Spannable;
import android.text.style.ImageSpan;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;

import org.sufficientlysecure.htmltextview.glide.DrawableCacheUtil;
import org.xml.sax.Attributes;

import java.util.HashMap;

/**
 * 想比于ImageGetter，可以获取img标签的其他属性,see {@link ImageTagHandler#startImg_(Editable, Attributes, HttpImageGetter)}
 */
public class HttpImageGetter implements Html.ImageGetter, IImageGetter {

    private TextView container;
    private Editable text;
    private boolean matchParentWidth;
    private HashMap<String, Boolean> loading;
    private HashMap<String, Point> imageSpanPositions;
    private HashMap<String, Boolean> imageSpanFirst;

    public HttpImageGetter(TextView textView) {
        this.container = textView;
        this.matchParentWidth = false;
        init();
    }


    public HttpImageGetter(Editable text, TextView textView) {
        this.container = textView;
        this.text = text;
        init();
    }

    public HttpImageGetter(TextView textView, boolean matchParentWidth) {
        this.container = textView;
        this.matchParentWidth = matchParentWidth;
        init();
    }


    void setText(Editable text) {
        this.text = text;
    }

    private void init() {
        loading = new HashMap<>();
        imageSpanPositions = new HashMap<>();
        // imageSpans = new HashMap<>();
        imageSpanFirst = new HashMap<>();
    }


    public Context getContext() {
        return container.getContext();
    }

    /**
     * 直接从缓存拿图片并移除自定义ImageSpan
     *
     * @param source -
     * @return
     */
    @Override
    public Drawable getDrawable(final String source) {
        Drawable resource = DrawableCacheUtil.getInstance().get(source);
        if (resource != null) {//
            int width = resource.getIntrinsicWidth();
            int height = resource.getIntrinsicHeight();
            if (container.getWidth() != 0 && width > container.getWidth()) {
                height = container.getWidth() * height / width;
                width = container.getWidth();
            }
            resource.setBounds(0, 0, width, height);
            setIsFirst(false, source);
        } else {
            resource = getContext().getResources().getDrawable(R.drawable.empty_holder);
            setIsFirst(true, source);
        }
        return resource;
    }


    public boolean isFirst(String src) {
        if (imageSpanFirst.containsKey(src)) {
            return imageSpanFirst.get(src);
        }
        return true;

    }


    public void setIsFirst(boolean isFirst, String src) {
        imageSpanFirst.put(src, isFirst);
    }

    /**
     * 网络下载图片并缓存到LRU
     *
     * @param source -
     * @param width  img 标签的width属性
     * @param height img 标签的height属性
     * @return
     */
    @Override
    public void loadDrawable(final String source, String width, String height) {
        Drawable drawable = DrawableCacheUtil.getInstance().get(source);
        if (drawable == null) {
            if (!loading.containsKey(source) || !loading.get(source)) {
                loading.put(source, true);
                Glide.with(container).load(source).into(new SimpleTarget<Drawable>() {
                    @Override
                    public void onResourceReady(Drawable resource, Transition<? super Drawable> transition) {
                        loading.remove(source);
                        //
                        int width = resource.getIntrinsicWidth();
                        int height = resource.getIntrinsicHeight();
                        if (width > container.getWidth()) {
                            height = container.getWidth() * height / width;
                            width = container.getWidth();
                        }
                        resource.setBounds(0, 0, width, height);
                        DrawableCacheUtil.getInstance().put(source, resource);
                        //
                        //invalidate(container, text);
                        setImageSpan(resource, source);
                    }
                });
            }
        }
    }

    @Override
    public void imgTagPosition(String source, int start, int end) {
        imageSpanPositions.put(source, new Point(start, end));
    }


    /**
     * 网络请求获取图片后重新刷新并绑定点击事件
     */
    protected void invalidate(TextView container, Editable text) {
        /**重新设置是为了走 {@link #getDrawable(String)}**/
        //container.getEditableText();
        container.setText(text);
        //container.setText(Html.fromHtml(text, this, null));
    }

    /**
     * 添加自定义的ImageSpan
     *
     * @param d
     * @param src
     */
    private void setImageSpan(Drawable d, String src) {
        Point position = imageSpanPositions.get(src);
        int start = position.x;
        int end = position.y;
        text.setSpan(new ImageSpan(d, src), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        container.setText(text);
        container.invalidate();
    }


    private float getScale(Drawable drawable) {
        if (!matchParentWidth || container == null) {
            return 1f;
        }
        float maxWidth = container.getWidth();
        float originalDrawableWidth = drawable.getIntrinsicWidth();
        return maxWidth / originalDrawableWidth;
    }

}
